#pragma once
#include <map>
#include "messageHandler.h"
#include "loggerFactory.h"
#include "appException.h"

template<typename T,typename Q>
class MessageDispatcher
{
public:
	~MessageDispatcher();
	bool regist(const T& command, MessageHandler<T, Q>* handler);
	void dispatch(Protocol<T>* packet, const Q& attachment);
private:
	std::map<T, MessageHandler<T, Q>*> handlers;
	static log4cpp::Category& logger;
};

template<typename T, typename Q>
log4cpp::Category& MessageDispatcher<T,Q>::logger = LoggerFactory::getLogger("MessageDispatcher");

template<typename T, typename Q>
inline MessageDispatcher<T, Q>::~MessageDispatcher()
{
	if (!handlers.empty()) {
		typename std::map<T, MessageHandler<T, Q>*>::iterator it = handlers.begin();
		while (it != handlers.end())
		{
			delete it->second;
			it->second = NULL;
			++it;
		}
	}
}

template<typename T, typename Q>
bool MessageDispatcher<T, Q>::regist(const T& command, MessageHandler<T, Q>* handler)
{
	if (!handler) {
		return false;
	}
	handlers.insert(std::make_pair(command, handler));
	return true;
}

template<typename T, typename Q>
inline void MessageDispatcher<T, Q>::dispatch(Protocol<T>* packet, const Q& attachment)
{
	typename std::map<T, MessageHandler<T, Q>*>::iterator it = handlers.find(packet->command());
	if (it == handlers.end()) {
		logger.error("handler for cmd:%s not found", packet->command());
		return;
	}
	if (it->second) {
		it->second->handle(packet, attachment);
	}
}